﻿
using Microsoft.AspNetCore.Mvc;

namespace RuoVea.Fams.Server.Service;

/// <summary>
/// 
/// </summary>

[ApiExplorerSettings(GroupName = "fams")]
public partial class AssetsService : IApplicationService
{
    /// <summary>
    /// 
    /// </summary>
    private readonly SugarRepository<FamsAssets> _thisRepository;
    private readonly ICurrentUser _currentUser;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="thisRepository"></param>
    /// <param name="currentUser"></param>
    public AssetsService(SugarRepository<FamsAssets> thisRepository, ICurrentUser currentUser)
    {
        _thisRepository = thisRepository;
        _currentUser = currentUser;
    }

    /// <summary>
    /// 查询所有/分页
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns> 
    public async Task<RestfulResult<PageResult<FamsAssets>>> GetPagesAsync(AssetsPageParam? data)
    {
        var restful = new RestfulResult<PageResult<FamsAssets>>() { Code = CodeStatus.OK };
        data ??= new AssetsPageParam { PageNo = 1, PageSize = 10 };
        var query = await _thisRepository.AsQueryable()
            //.Where(u => u.Creator == _currentUser.UserId)
            .ToPageAsync(data.PageNo, data.PageSize);

        restful.Data = query;
        return restful;
    }

    /// <summary>
    /// 所有
    /// </summary>
    /// <returns></returns>
    public async Task<RestfulResult<List<FamsAssets>>> GetlistAsync()
    {
        var restful = new RestfulResult<List<FamsAssets>>() { Code = CodeStatus.OK };
        PageParam data = new PageParam { PageNo = 1, PageSize = 100 };
        var query = await _thisRepository.AsQueryable()
             //.Where(u => u.IsDisable == YesOrNot.N)
             //.Where(u => u.Creator == _currentUser.UserId)
             .OrderByDescending(u => u.PurchaseDate)
             .Select(u => new FamsAssets
             {
                 Id = u.Id,
                 Code = u.Code,
                 Name = u.Name,
                 Type = u.Type
             })
            .ToListAsync();
        restful.Data = query;
        return restful;
    }

    /// <summary>
    /// 增加
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task<RestfulResult> AddAsync(FamsAssets data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };
        // 验证必填字段
        if (string.IsNullOrEmpty(data.Code))
            throw new ArgumentException("资产编码不能为空");

        if (data.PurchaseDate > DateTime.Now)
            throw new ArgumentException("购入日期不能晚于当前日期");

        // 自动计算折旧
        CalculateDepreciation(data);

        var isExist = await _thisRepository.IsAnyAsync(u => u.Code == data.Code && u.Creator == _currentUser.UserId);
        if (isExist)
        {
            restful.Message = "资产编码重复";
            return restful;
        }
        data.Creator = _currentUser.UserId;
        bool result = await _thisRepository.InsertAsync(data);
        if (result)
        {
            restful.Data = result;
            restful.Code = CodeStatus.OK;
            return restful;
        }
        else
        {
            restful.Message = "添加失败";
            return restful;
        }
    }

    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task<RestfulResult> UpdateAsync(FamsAssets data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };
        // 验证必填字段
        if (string.IsNullOrEmpty(data.Code))
            throw new ArgumentException("资产编码不能为空");

        if (data.PurchaseDate > DateTime.Now)
            throw new ArgumentException("购入日期不能晚于当前日期");

        // 自动计算折旧
        CalculateDepreciation(data);

        var isExist = await _thisRepository.IsAnyAsync(u => u.Id == data.Id && u.Creator == _currentUser.UserId);
        if (!isExist)
        {
            restful.Message = "记录不存在";
            return restful;
        }
        bool result = await _thisRepository.UpdateAsync(data, true, true, "资产修改");
        if (result)
        {
            restful.Data = result;
            restful.Code = CodeStatus.OK;
            return restful;
        }
        else
        {
            restful.Message = "修改失败";
            return restful;
        }
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns> 
    public async Task<RestfulResult> DeleteAsync([FromBody] EntityBaseId data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };

        if (data.Id == 0)
        {
            restful.Message = "删除失败";
            return restful;
        }
        bool isDelete = await _thisRepository.DeleteByIdAsync(data.Id);
        if (isDelete)
        {
            restful.Data = isDelete;
            restful.Message = "删除成功";
            restful.Code = CodeStatus.OK;
            return restful;
        }
        else
        {
            restful.Data = isDelete;
            restful.Message = "删除失败";
            return restful;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="assetId"></param>
    /// <param name="disposalDate"></param>
    /// <param name="reason"></param>
    /// <returns></returns>
    public async Task<bool> SetDisposal(long assetId, DateTime disposalDate, string reason)
    {
        var asset = await _thisRepository.AsQueryable().FirstAsync(x => x.Id == assetId);
        if (asset == null) return false;

        asset.DisposalDate = disposalDate;
        asset.DisposalReason = reason;
        asset.Status = "已报废";

        return await _thisRepository.UpdateAsync(asset);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="asset"></param>
    /// <exception cref="ArgumentException"></exception>
    private void CalculateDepreciation(FamsAssets asset)
    {
        if (asset.OriginalValue <= 0 || asset.UsefulLife <= 0 || asset.ResidualRate < 0)
        {
            throw new ArgumentException("折旧计算参数无效");
        }

        decimal residualValue = asset.OriginalValue * (asset.ResidualRate / 100m);
        decimal depreciableAmount = asset.OriginalValue - residualValue;

        // 计算月折旧额
        asset.MonthlyDepreciation = Math.Round(depreciableAmount / (asset.UsefulLife * 12), 2);

        // 计算累计折旧
        DateTime startDate = asset.DepreciationStartDate;
        DateTime now = DateTime.Now;

        int monthsDiff = (now.Year - startDate.Year) * 12 + (now.Month - startDate.Month);
        monthsDiff = Math.Max(0, monthsDiff); // 确保不为负数

        asset.DepreciationYears = monthsDiff / 12;
        asset.AccumulatedDepreciation = Math.Round(Math.Min(monthsDiff * asset.MonthlyDepreciation.Value, depreciableAmount), 2);
        asset.NetValue = Math.Round(asset.OriginalValue - asset.AccumulatedDepreciation.Value, 2);
    }
}

